-- AccompanyDisplay
-- Created by dengc Oct/26/2016
-- 伴生物外观显示

require "game/ui/module/monster/MonsterAnimation"

-- MonsterDisplay继承自Node
AccompanyDisplay = class("AccompanyDisplay", function()
    return cc.Node:create();
end);

function AccompanyDisplay.create(id)
    return AccompanyDisplay.new(id);
end

-- 构造函数
function AccompanyDisplay:ctor(id)
    -- 记录怪物编号
    self.id = id;

    -- 创建普通动画
    local animName = AccompanyDisplayM.query(id, "normal_anima");
    local animation = MonsterAnimation.create("animation/" .. animName .. ".csb");
    animation:setName("normal_anima");
    self.normalAnimation = animation;
    setHighLightMode(self.normalAnimation, false);
    self:addChild(animation);

    -- 死亡动画
    local dieAnim =  AccompanyDisplayM.query(self.id, "die_anima");
    local dieAnimation = MonsterAnimation.create("animation/" .. dieAnim .. ".csb");
    self.dieAnimation = dieAnimation;
    self:addChild(dieAnimation);
    dieAnimation:setVisible(false);

    -- 默认播放待机动作
    self:gotoIdle();

    self:registerScriptHandler(function(ev)
        if ev == "exitTransitionStart" then
            if self.normalAnimation then
                if self.normalAnimation.action then
                    self.normalAnimation.action:clearFrameEventCallFunc();
                end

                self.normalAnimation:destroy();
            end

            if self.dieAnimation then
                if self.dieAnimation.action then
                    self.dieAnimation.action:clearFrameEventCallFunc();
                end
                self.dieAnimation:destroy();
            end
        end
    end);
end

-- 切换怪物动作
function AccompanyDisplay:switchAction(actionType, extra)
    -- 待机
    if MONSTER_ACTION_IDLE == actionType then
        self:gotoIdle();
    -- 受创
    elseif MONSTER_ACTION_DAMAGED == actionType then
        self:gotoDamaged();
    -- 死亡
    elseif MONSTER_ACTION_DIE == actionType then
        self:gotoDie();
    elseif MONSTER_ACTION_STRIKE_BACK == actionType then
    -- 反击
        self:gotoStrikeBack();
    -- 交替伴生动作
    elseif MONSTER_ACTION_ACCOMPANY == actionType then
        self:gotoAccompany();
    else
        -- 暂不支持
        cclog("### 未知的怪物动作类型：" .. tostring(actionType));
    end
end

-- 播放待机动作
function AccompanyDisplay:gotoIdle()
    if self.normalAnimation == nil then
        return;
    end

    -- 获取帧范围和播放速度
    local frameRange = AccompanyDisplayM.query(self.id, "idle_frame");
    local speed = AccompanyDisplayM.query(self.id, "idle_speed") * 0.67;

    -- 播放
    self.normalAnimation:play(MONSTER_ACTION_IDLE, true, frameRange[1], frameRange[2], speed);
    self:setHighlightMode(self.normalAnimation, false);

    -- 需要暂停
    if self.needPause then
        self.normalAnimation:pause();
    end
end

-- 变红
function AccompanyDisplay:setHighlightMode(node, flag)
    if not node then
        return;
    end

    local children = node:getChildren();
    local len = table.getn(children)
    for i = 1, len do
        local child = children[i];
        local sprite = tolua.cast(child,"cc.Sprite");
        if sprite then
            setHighLightMode(sprite, flag);
        end

        self:setHighlightMode(child, flag);
    end
end

-- 震动
function AccompanyDisplay:shake()
    local offset = 20;
    local angle = 30;

    local moveRight = cc.MoveBy:create(0.05, cc.p(offset, 10));
    local rotateTo = cc.RotateTo:create(0.05, angle, angle);
    local delay = cc.DelayTime:create(0.1);
    local moveBack = cc.MoveBy:create(0.05, cc.p(-offset, -10));
    local rotateBack = cc.RotateTo:create(0.05, 0, 0);
    local callFunc = cc.CallFunc:create(function()
        self:setHighlightMode(self.normalAnimation, false);
    end);
    local action = cc.Sequence:create(cc.Spawn:create(moveRight, rotateTo), delay, cc.Spawn:create(moveBack, rotateBack), callFunc);

    self:runAction(action);
    self:setHighlightMode(self.normalAnimation, true);
end

-- 播放受创动作
function AccompanyDisplay:gotoDamaged()
    if self.normalAnimation == nil then
        return;
    end

    -- 获取帧范围和播放速度
    local frameRange = AccompanyDisplayM.query(self.id, "damaged_frame");
    local speed = AccompanyDisplayM.query(self.id, "damaged_speed");

    if speed == 0 then
        -- 没有受创动作， 改为震动效果
        self:shake();
        return;
    end

    -- 播放
    self.normalAnimation:play(MONSTER_ACTION_DAMAGED, false, frameRange[1], frameRange[2], speed);

    -- 注册帧回调函数
    self:registerFrameEvent(frameRange[2]);
end

-- 播放反击动作
function AccompanyDisplay:gotoStrikeBack()
    if self.normalAnimation == nil then
        return;
    end

    -- 获取帧范围和播放速度
    local classId = AccompanyDisplayM.query(id, "class_id");
    local frameRange = MonsterM.query(classId, "strike_back_frame");
    local speed = MonsterM.query(classId, "strike_back_speed");

    if speed == 0 then
        -- 没有反击动作， 改为受创效果
        self:gotoDamaged();
        return;
    end

    -- 播放
    self.normalAnimation:play(MONSTER_ACTION_STRIKE_BACK, false, frameRange[1], frameRange[2], speed);

    -- 注册帧回调函数
    self:registerFrameEvent(frameRange[2]);
end

-- 播放死亡动作
function AccompanyDisplay:gotoDie()
    -- 显示死亡动画
    self.dieAnimation:setVisible(true);

    -- 获取帧范围和播放速度
    local frameRange = AccompanyDisplayM.query(self.id, "die_frame");
    local speed = AccompanyDisplayM.query(self.id, "die_speed");

    -- 播放
    self.dieAnimation:play(MONSTER_ACTION_DIE, false, frameRange[1], frameRange[2], speed);
end

-- 播放交替伴生动作
function AccompanyDisplay:gotoAccompany()
    -- 保持待机状态就好
    self:gotoIdle();
end

-- 注册帧回调函数
-- @param endIndex   结束帧
function AccompanyDisplay:registerFrameEvent(endIndex)
    -- 移除帧回调处理函数
    self.normalAnimation.action:clearFrameEventCallFunc();

    -- 帧回调处理函数
    local function onFrameEvent(frame)
        if nil == frame or nil == self.normalAnimation then
            return;
        end

        -- 使用pilor帧，确保每帧都会有回调过来
        if frame.getEvent and frame:getEvent() == "pilor" then
            -- 帧索引的下标是从0开始的，而配置的下标是从1开始的，故这里要加1
            local frameIndex = frame:getFrameIndex() + 1;

            -- 尚未到达结束帧，不处理
            if frameIndex ~= endIndex - 1 then
                return;
            end

            -- 移除帧回调处理函数
            self.normalAnimation.action:clearFrameEventCallFunc();

            local function callback()
                -- 切换至待机状态
                self:gotoIdle();
            end

            performWithDelay(self, callback, 0.1);
        end
    end

    -- 设置帧回调处理函数
    self.normalAnimation.action:setFrameEventCallFunc(onFrameEvent);
end

-- 移除普通动画
function AccompanyDisplay:removeNormalAnimation()
    if self.normalAnimation == nil then
        return;
    end

    self.normalAnimation:pause();
    self.normalAnimation:destroy();
    self.normalAnimation = nil;
end

-- 暂停所有动画
function AccompanyDisplay:pauseActions()
    if self.normalAnimation == nil then
        return;
    end

    -- 设置暂停
    self:setNeedPause(true);
    self:gotoIdle();
    -- self.normalAnimation:pause();
end

-- 设置是否需要暂停
function AccompanyDisplay:setNeedPause(needPause)
    --self.needPause = needPause;
end
